package com.xjrsoft.module.base.utils;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xjrsoft.core.tool.node.ForestNodeMerger;
import com.xjrsoft.core.tool.node.INode;
import com.xjrsoft.core.tool.utils.BeanUtil;
import com.xjrsoft.core.tool.utils.CollectionUtil;
import com.xjrsoft.core.tool.utils.StringPool;
import com.xjrsoft.core.tool.utils.StringUtil;
import com.xjrsoft.module.base.constants.ModuleConstants;
import com.xjrsoft.module.base.dto.ISubModuleDto;
import com.xjrsoft.module.base.entity.*;
import com.xjrsoft.module.base.vo.*;
import com.xjrsoft.module.form.constant.FormConstants;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class ModuleUtils {
    private ModuleUtils() {}

    public static void buildAuthBtnVo(List<XjrBaseModuleButton> btnList, Map<String, ModuleOtherVo> moduleOtherVoMap,List<String> authCodeList){

        if (CollectionUtil.isNotEmpty(btnList)) {
            for (XjrBaseModuleButton btn : btnList) {
                ModuleOtherVo moduleOtherVo = moduleOtherVoMap.get(btn.getModuleId());
                if (moduleOtherVo == null) {
                    moduleOtherVo = new ModuleOtherVo();
                    moduleOtherVoMap.put(btn.getModuleId(), moduleOtherVo);
                }

                //权限code  默认格式为   moduleid:buttonEnCode
                authCodeList.add(btn.getEnCode());
                moduleOtherVo.getButtons().add(btn.getEnCode());
            }
        }
    }

    public static void buildAuthColVo(List<XjrBaseModuleColumn> btnList, Map<String, ModuleOtherVo> moduleOtherVoMap){
        if (CollectionUtil.isNotEmpty(btnList)) {
            for (XjrBaseModuleColumn col : btnList) {
                ModuleOtherVo moduleOtherVo = moduleOtherVoMap.get(col.getModuleId());
                if (moduleOtherVo == null) {
                    moduleOtherVo = new ModuleOtherVo();
                    moduleOtherVoMap.put(col.getModuleId(), moduleOtherVo);
                }
                Map<String, String> colVo = new HashMap<>(2);
                colVo.put("label", col.getFullName());
                colVo.put("prop", col.getEnCode());
                moduleOtherVo.getColumns().add(colVo);
            }
        }
    }

    public static void buildAuthFormVo(List<XjrBaseModuleForm> formList, Map<String, ModuleOtherVo> moduleOtherVoMap){
        if (CollectionUtil.isNotEmpty(formList)) {
            List<ModuleFormVo> moduleFormVoList = ForestNodeMerger.merge(BeanUtil.copyList(formList, ModuleFormVo.class));
            for (ModuleFormVo form : moduleFormVoList) {
                ModuleOtherVo moduleOtherVo = moduleOtherVoMap.get(form.getModuleId());
                if (moduleOtherVo == null) {
                    moduleOtherVo = new ModuleOtherVo();
                    moduleOtherVoMap.put(form.getModuleId(), moduleOtherVo);
                }
                List<INode> children = form.getChildren();
                Set<Object> forms = moduleOtherVo.getForms();
                String enCode = form.getEnCode();
                if (CollectionUtil.isNotEmpty(children)) {
                    Map<String, Set<String>> tabFieldMap = null;
                    for (Object obj : forms) {
                        if (obj instanceof Map) {
                            Map<String, Set<String>> map = (Map<String, Set<String>>) obj;
                            if (map.keySet().contains(enCode)) {
                                tabFieldMap = map;
                            }
                        }
                    }
                    if (tabFieldMap == null) {
                        tabFieldMap = new HashMap<>();
                        forms.add(tabFieldMap);
                    }
                    Set<String> tabFields = new LinkedHashSet<>();
                    for (INode child : children) {
                        ModuleFormVo tabField = (ModuleFormVo) child;
                        tabFields.add(tabField.getEnCode());
                    }
                    Set<String> subFields = tabFieldMap.get(enCode);
                    if (subFields == null) {
                        tabFieldMap.put(enCode, tabFields);
                    } else {
                        subFields.addAll(tabFields);
                    }
                } else {
                    forms.add(enCode);
                }
            }
        }
    }

    public static <T extends IModuleVo> List<ModuleVo> buildSubModuleTree(List<ModuleVo> moduleVoList, List<?> moduleSubList, Class<T> subModuleClazz) {
        List<ModuleVo> subModuleVoList = BeanUtil.deepCopy(moduleVoList);
        Map<String, ModuleVo> subModuleMap = new HashMap<>();
        subModuleVoList.forEach(moduleVo ->{
            if (StringUtil.equalsIgnoreCase(moduleVo.getTarget(), "iframe")) {
                subModuleMap.put(moduleVo.getModuleId(), moduleVo);
            }
        });
        List<T> moduleSubVoList = BeanUtil.copyList(moduleSubList, subModuleClazz);
        List<T> moduleSubVoTreeList = ForestNodeMerger.merge(moduleSubVoList);
//        Set<String> subModuleIdList = new LinkedHashSet<>();
        moduleSubVoTreeList.forEach(moduleSubVoTree -> {
            String moduleId = moduleSubVoTree.getModuleId();
            ModuleVo moduleVo = subModuleMap.get(moduleId);
            if (moduleVo != null) {
                moduleVo.getChildren().add(moduleSubVoTree);
//                subModuleIdList.add(moduleId);
            }
        });
//         移除没有按钮、列表字段、表单字段的菜单
        ForestNodeMerger.merge(subModuleVoList);
        List<ModuleVo> resultList = subModuleVoList.stream().filter(ModuleUtils::isEmptySubModule
        ).collect(Collectors.toList());
        resultList.forEach(resultModule -> {
            List<INode> children = resultModule.getChildren();
            if (CollectionUtil.isNotEmpty(children) && children.get(0) instanceof ModuleVo) {
                resultModule.setChildren(null);
            }
        });

        return ForestNodeMerger.merge(resultList);
    }

    private static boolean isEmptySubModule(ModuleVo moduleVo) {
        List<INode> children = moduleVo.getChildren();
        if (CollectionUtil.isNotEmpty(children)) {
            if (children.get(0) instanceof ModuleVo){
                for (INode node : children) {
                    ModuleVo subModule = (ModuleVo) node;
                    if (isEmptySubModule(subModule)) {
                        return true;
                    }
                }
                return false;
            }
            return true;
        }
        return false;
    }
    
    public static List<XjrBaseModuleButton> buildButtonEntities(String moduleId, String moduleEnCode, JSONArray buttons) {
        List<XjrBaseModuleButton> resultList = new ArrayList<>();
//        if (CollectionUtil.isNotEmpty(buttons)) {
            int sortCode = 0;
            for (Object obj : buttons) {
                JSONObject button = (JSONObject) obj;
                if (!MapUtils.getBoolean(button, "checked", false)) {
                    continue;
                }
                XjrBaseModuleButton addBtn = new XjrBaseModuleButton();
                addBtn.setModuleId(moduleId);
                addBtn.setFullName(button.getString("name"));
                addBtn.setEnCode( moduleEnCode + ":" + button.getString("val"));
                addBtn.setParentId(StringPool.ZERO);
                addBtn.setSortCode(sortCode++);
                resultList.add(addBtn);
            }
//        }

        return resultList;
    }

    public static List<XjrBaseModuleColumn> buildColumnEntities(String moduleId, JSONArray columnsJson) {
        List<XjrBaseModuleColumn> resultList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(columnsJson)) {
            for (Object columnObj : columnsJson) {
                XjrBaseModuleColumn column = new XjrBaseModuleColumn();
                JSONObject columnJson = (JSONObject) columnObj;
                column.setModuleColumnId(IdWorker.get32UUID());
                column.setModuleId(moduleId);
                column.setParentId(StringPool.ZERO);
                String label = columnJson.getString("label");
                column.setFullName(label != null ? label : columnJson.getString(ModuleConstants.COLUMN_NAME));
                column.setEnCode(columnJson.getString(ModuleConstants.COLUMN_FIELD));
                column.setSortCode(columnJson.getInteger(ModuleConstants.COLUMN_INDEX));
                resultList.add(column);
            }
        }
        return resultList;
    }


    public static List<XjrBaseModuleForm> buildFormEntities(String moduleId, List<Map<String, Object>> fieldsJson) {
        return buildFormEntities(moduleId, null, fieldsJson);
    }

    private static List<XjrBaseModuleForm> buildFormEntities(String moduleId, String parentId, List<Map<String, Object>> fieldsJson) {
        List<XjrBaseModuleForm> resultList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(fieldsJson)) {
            for (Object fieldObj : fieldsJson) {
                Map<String, Object> fieldJson = (Map<String, Object>) fieldObj;
                Map<String, Object> configJson = MapUtils.getMap(fieldJson, ModuleConstants.FORM_FIELD_CONFIG);
                String componentName = MapUtils.getString(configJson, "componentName");
                if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
                    Map<String, Object> tabsMap = MapUtils.getMap(configJson, "childrenObj");
                    for (Object obj : tabsMap.values()) {
                        resultList.addAll(buildFormEntities(moduleId, null, (List<Map<String, Object>>) obj));
                    }
                } else if (StringUtil.equalsIgnoreCase(componentName, "table")) {
                    List<Map<String, Object>> children = (List<Map<String, Object>>) configJson.get(ModuleConstants.FORM_CHILDREN);
                    XjrBaseModuleForm tabModuleForm = buildModuleForm(moduleId, fieldJson);
                    String tabModuleFormId = IdWorker.get32UUID();
                    tabModuleForm.setModuleFormId(tabModuleFormId);
                    tabModuleForm.setFullName(MapUtils.getString(configJson, "componentTitle"));
                    tabModuleForm.setEnCode(MapUtils.getString(configJson, FormConstants.BIND_TABLE));
                    tabModuleForm.setParentId(StringPool.ZERO);
                    resultList.add(tabModuleForm);
                    resultList.addAll(buildFormEntities(moduleId, tabModuleFormId, children));
                } else {
                    XjrBaseModuleForm moduleForm = buildModuleForm(moduleId, configJson);
                    moduleForm.setParentId(StringUtils.defaultIfEmpty(parentId, StringPool.ZERO));
                    resultList.add(moduleForm);
                }
            }
        }
        return resultList;
    }

    private static XjrBaseModuleForm buildModuleForm(String moduleId, Map<String, Object> configJson) {
        XjrBaseModuleForm field = new XjrBaseModuleForm();
        field.setModuleFormId(IdWorker.get32UUID());
        field.setModuleId(moduleId);
        field.setFullName(MapUtils.getString(configJson, ModuleConstants.FORM_FIELD_LABEL));
        field.setEnCode(MapUtils.getString(configJson, ModuleConstants.FORM_FIELD));
        field.setLgMarkCode(MapUtils.getString(configJson, "F_LgMarkCode"));
        return field;
    }

    public static SystemModuleTreeVo buildSystemModule(List<ModuleVo> moduleList, List<XjrBaseSubsystem> subsystemList) {
        List<ModuleVo> moduleTreeList = ForestNodeMerger.merge(moduleList);
        return buildSystemModuleVo(moduleTreeList, subsystemList);
    }

    public static SystemModuleTreeVo buildSystemModuleVo(List<ModuleVo> moduleTreeList, List<XjrBaseSubsystem> subsystemList) {
        List<ModuleVo> mainModuleList = new ArrayList<>();
        List<SubSystemTreeVo> subSystemTreeVoList = BeanUtil.copyList(subsystemList, SubSystemTreeVo.class);
        for (ModuleVo moduleVo : moduleTreeList) {
            if (StringUtil.equalsIgnoreCase(moduleVo.getSubSystemId(), "0")) {
                mainModuleList.add(moduleVo);
                continue;
            }
            if (CollectionUtil.isNotEmpty(subsystemList)) {
                for (SubSystemTreeVo subSystemTreeVo : subSystemTreeVoList) {
                    if (StringUtil.equalsIgnoreCase(subSystemTreeVo.getId(), moduleVo.getSubSystemId())) {
                        subSystemTreeVo.getModuleVoList().add(moduleVo);
                    }
                }
            }
        }
        SystemModuleTreeVo systemModuleTreeVo = new SystemModuleTreeVo();
        systemModuleTreeVo.setModuleVoList(mainModuleList);
        systemModuleTreeVo.setSubSystemTreeVoList(subSystemTreeVoList);
        return systemModuleTreeVo;
    }

    public static <T extends ISubModuleDto> List<T> buildFullChildrenList(T subModuleDto) {
        List<T> resultList = new ArrayList<>();
        List<T> children = subModuleDto.getChildren();
        if (CollectionUtil.isNotEmpty(children)) {
            if (StringUtil.isEmpty(subModuleDto.getId())) {
                subModuleDto.setId(IdWorker.get32UUID());
            }
            for (T child : children) {
                child.setParentId(subModuleDto.getId());
                resultList.addAll(buildFullChildrenList(child));
            }
        }
        resultList.add(subModuleDto);
        return resultList;
    }
}
